package com.sec.etech.ism.service;

import com.alibaba.fastjson.JSONObject;
import com.sec.etech.ism.constant.SignatureConstant;
import com.sec.etech.ism.factory.IsmFactory;
import com.sec.etech.ism.model.IsmAppSetting;
import com.sec.etech.ism.model.IsmServiceDef;
import com.sec.etech.ism.model.IsmTask;
import com.sec.etech.ism.model.MaterialNoLog;
import com.sec.etech.ism.util.EtechSignatureUtil;
import org.openbpm.base.api.exception.BusinessException;
import org.openbpm.base.api.exception.BusinessMessage;
import org.openbpm.base.core.util.StringUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * 服务统一入口及工具类
 */
@Service
public class IsmService {
    @Resource
    private IsmTaskService ismTaskService;
    @Resource
    private IsmTaskLogService ismTaskLogService;
    @Resource
    private IsmAppSettingService ismAppSettingService;
    @Resource
    private IsmServiceDefService ismServiceDefService;
    @Resource
    private MaterialNoLogService materialNoLogService;

    // 调用第三方接口
    public JSONObject call3rdService(String sysCode, String serviceCode, JSONObject paramJson) throws BusinessException {
        JSONObject result = null;
        // 1. 检查系统和服务参数配置
        try{
            this.getServiceDef(sysCode, serviceCode, 2);
            // 2. 调用服务
            // 优先级：
            // 1 定制服务实现类    getNcByNum => ismGetNcByNumServiceImpl
            // 真实参数调用，去掉外壳
            IsmMethodService ismMethodService = IsmFactory.getIsmMethodService(serviceCode);
            return ismMethodService.call(sysCode, serviceCode, paramJson);
        }catch(Exception e){
            result = new JSONObject(2);
            result.put("flag", "fail");
            String msg = e.getLocalizedMessage();
            if(StringUtil.isEmpty(msg)){
                msg = e.getMessage();
            }
            result.put("msg", msg!=null ? msg : "接口调用" + sysCode + "接口异常请联系Etech管理员处理！");
            Long taskId = ismTaskService.saveOrUpdateTask(sysCode, serviceCode, serviceCode, paramJson.toJSONString());
            //保存接口调用日志
            ismTaskLogService.saveLog(taskId, serviceCode, null, null,null, paramJson.toJSONString(), result);
            e.printStackTrace();
            return result;
        }
    }

    // 统一对外服务（供第三方调用）
    public JSONObject callService(String sysCode, String serviceCode, JSONObject paramJson) {
        JSONObject result = null;
        // 1. 参数及权限检查
        try{
            // 检查调用参数及权限
            this.checkService(sysCode, serviceCode, paramJson);

            // 2. 查找服务
            // 优先级：
            // 1 定制服务实现类    getNcByNum => ismGetNcByNumServiceImpl
            // 真实参数调用，去掉外壳
            IsmMethodService ismMethodService = IsmFactory.getIsmMethodService(serviceCode);
            result = ismMethodService.call(sysCode, serviceCode, paramJson);
        }catch(Exception e){
            result = new JSONObject(2);
            result.put("flag", "fail");
            String msg = e.getLocalizedMessage();
            if(StringUtil.isEmpty(msg)){
                msg = e.getMessage();
            }
            result.put("msg", msg!=null ? msg : "接口调用异常请联系Etech管理员处理！");
            Long taskId = ismTaskService.saveOrUpdateTask(sysCode, serviceCode, serviceCode, paramJson.getString(SignatureConstant.INPUT_PARAMS));
            //保存接口调用日志
            ismTaskLogService.saveLog(taskId, serviceCode, null, serviceCode,null, paramJson.toJSONString(), result);
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 根据appName和任务ID调用接口
     * @param taskId
     * @throws Exception
     */
    public String callByTaskId(Long taskId) throws Exception {
        IsmTask ismTask = ismTaskService.getById(taskId);
        IsmMethodService ismMethodService = IsmFactory.getIsmMethodService(ismTask.getMethodName());
        JSONObject result = ismMethodService.call(ismTask.getSysCode(), ismTask.getBusinessCode(),
                JSONObject.parseObject(ismTask.getBusinessParams()));
        return result!=null ? result.getString("msg") : "重试失败，请检查数据！";
    }
    //检查参数、校验权限并获取服务信息
    private IsmServiceDef getServiceDef(String sysCode, String serviceCode, int type) throws BusinessMessage {
        // 1 参数检查及服务获取
        // 1.1 检查必要参数
        if(StringUtil.isEmpty(sysCode)){
            throw new BusinessMessage("[ISM]外部系统sysName must not null");
        }
        if(StringUtil.isEmpty(serviceCode)){
            throw new BusinessMessage("[ISM]服务名serviceName must not null");
        }
        // 1.2 检查第三方系统名获取定义
        IsmAppSetting ismAppSetting = ismAppSettingService.getByCode(sysCode);
        if(ismAppSetting==null){
            throw new BusinessMessage(String.format("[ISM]外部系统sysCode：%s无法找到，如需配置请联系ETech相关人员", sysCode));
        }
        // 1.3 服务名称和服务定义
        if(serviceCode.indexOf(".")>0){
            // 只支持存在一个.
            String[] tt = serviceCode.split(".");
            serviceCode = tt[1].trim();
        }
        IsmServiceDef serviceDef = ismServiceDefService.getByCode(serviceCode);
        if(serviceDef==null){
            throw new BusinessMessage(String.format("[ISM]服务名serviceCode：%s无法找到，如需定制请联系ETech相关人员", serviceCode));
        }
        // 1.4
        serviceDef.setRefAppSetting(ismAppSetting);
        // 2. 检查权限
        // 2.1 是当前主应用
        if(type==2) {//调用第三方
            return serviceDef;
        }else if(type==1) {//被第三方调用 2.2 访问权限
            String strAccessRights = serviceDef.getAccessRights();
            JSONObject rightsJson = JSONObject.parseObject(strAccessRights);
            // {"app":["mes"]}
            if(rightsJson.containsKey("app")){
                if(!rightsJson.getString("app").contains(sysCode.toLowerCase())){
                    throw new BusinessMessage("无此接口，如需定制请联系ETech相关人员！");
                }
            }
        }
        return serviceDef;
    }

    boolean checkService(String sysCode, String serviceCode, JSONObject paramJson) throws BusinessMessage {
        // 1. 检查系统和服务参数配置
        IsmServiceDef serviceDef = this.getServiceDef(sysCode, serviceCode, 1);
        IsmAppSetting ismAppSetting = serviceDef.getRefAppSetting();

        // 2.2 签名
        //检查参数、签名是否一致、是否失效
        JSONObject defParams = JSONObject.parseObject(serviceDef.getParams());
        String checkMsg = null;
        try {
            checkMsg = EtechSignatureUtil.checkSignature(paramJson, ismAppSetting.getAppKey1(), defParams.getInteger("validTime"));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        if(checkMsg!=null) {
            throw new BusinessMessage(checkMsg);
        }
        return true;
    }

    /**
     * 生成签名接口
     * @param inputParams
     * @param appSecrete
     * @return
     * @throws Exception
     */
    public JSONObject signature(JSONObject inputParams, String appSecrete) throws Exception {
        return EtechSignatureUtil.buildRequestParams(inputParams, appSecrete);
    }

    /**
     * 重新获取/更新SAP物料号
     * @param logId
     * @return
     * @throws Exception
     */
    public String reCallMaterialNo(Long logId) throws Exception {
        MaterialNoLog materialNoLog = materialNoLogService.getById(logId);
        JSONObject object = JSONObject.parseObject(materialNoLog.getBusParams());
        String serviceCode = null;
        if(materialNoLog.getType()==1){//创建
            serviceCode = "createMaterialNo";
        }else if(materialNoLog.getType()==2){//更新
            serviceCode = "updateMaterialNo";
        }
        JSONObject result = this.call3rdService("SAP", serviceCode, object);
        if("success".equals(result.getString("flag"))){
            return "success";
        }else {
            return result.getString("msg");
        }
    }
}
